Angular架構使開發人員能夠將資料從父組件傳遞到子組件。子組件由可在HTML範本中顯示或進一步處理以產生新的結果。 Angular在signal
之前使用了@Input
,但Angular 17引入了可以從父組件輸入signal inputs
。
Signal input
可以是必需的 (required),也可以是可選的 (optional)。 必需的signal input
可以選擇傳入選項物件。可選signal input
輸入初始值,也可以選擇傳入選項物件。
選項物件包含兩個屬性
alias
- signal input
的別名transform
- 將輸入值轉換為最終值的函數import { Component, input } from '@angular/core';
@Component({
selector: 'app-star-war',
standalone: true,
template: `<p>Jedi Id: {{ jedi() }}</p>`,
})
export class StarWarComponent {
// required signal input
jedi = input.required<number>();
}
建立一個具有多個signal inputs的
StarWarComponent。
signal input與App
組件綁定。 該組件具有HTML範本顯示必需的訊號輸入, jedi
。
import { Component, VERSION } from '@angular/core';
import { StarWarComponent } from './star-war.component';
@Component({
selector: 'app-root',
standalone: true,
imports: [StarWarComponent],
template: `
<app-star-war [jedi]="1" starShip="Star Destroyer" rgbTuple="yellow" />
<app-star-war [jedi]="10" />`,
})
export class App {}
App
組件有兩個StarWarComponent
。 第一個StarWarComponent
的jedi
輸入是1,第二個StarWarComponent
的jedi
輸入是10。
import { Component, input } from '@angular/core';
@Component({
selector: 'app-star-war',
standalone: true,
template: `
<p>Jedi Id: {{ jedi() }}</p>
<p>Sith Id: {{ sith() }}</p>
`,
})
export class StarWarComponent {
// required signal input
jedi = input.required<number>();
// optional signal input with a value
sith = input(4);
}
sith
是可選的signal input,初始值為4。當未向組件提供sith
輸入值時,將使用初始值。
import { Component } from '@angular/core';
import { StarWarComponent } from './star-war.component';
@Component({
selector: 'app-root',
standalone: true,
imports: [StarWarComponent],
template: `
<app-star-war [jedi]="1" />
<app-star-war [jedi]="10" [sith]="44" />
`,
})
export class App {}
第一個StarWarComponent
沒有輸入sith
的值;因此,sith
為 4。第二個StarWarComponent
的 sith
為 44。
import { NgStyle } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { ChangeDetectionStrategy, Component, computed, effect, inject, Injector, input, signal } from '@angular/core';
import { getPerson, Person } from './star-war.api';
import { StarWarPersonComponent } from './star-war-person.component';
import { RgbType, validateRGB } from './rgb';
import { toObservable, toSignal } from '@angular/core/rxjs-interop';
import { switchMap } from 'rxjs';
@Component({
selector: 'app-star-war',
standalone: true,
imports: [NgStyle, StarWarPersonComponent],
template: `
<h3>Star War Jedi vs Sith</h3>
<div [ngStyle]="backgrounStyle()">
<div style="display: flex; justify-content: space-between;">
<p>Jedi Id: {{ jedi() }}</p>
<p>Sith Id: {{ sith() }}</p>
<p>Star ship: {{ ship() }}</p>
</div>
<app-star-war-person [person]="fighter()" kind="Jedi Fighter" />
<app-star-war-person [person]="sithLord()" kind="Sith Lord" />
</div>
`,
})
export class StarWarComponent {
// required signal input
jedi = input.required<number>();
// optional signal input with a value
sith = input(4);
// signal input with alias
ship = input('Star Destroyer', { alias: 'starShip' })
// signal input with transform
rgbs = input.required({
alias: 'rgbTuple',
transform: (v: RgbType) => validateRGB(v)
});
}
ship
signal input的別名是 starShip
。 Signal 的初始值為"Star Destroyer"。rgbs
signal input的別名是 rgbTuple
。
import { Component } from '@angular/core';
import { StarWarComponent } from './star-war.component';
@Component({
selector: 'app-root',
standalone: true,
imports: [StarWarComponent],
template: `
<app-star-war [jedi]="1" rgbTuple="yellow" />
<app-star-war [jedi]="10" [sith]="44" starShip="Jedi starfighter" [rgbTuple]="lightBlue" />`,
})
export class App {
lightBlue = [137, 207, 240] as [number, number, number];
}
在第二個 StarWarComponent
中,輸入名稱分別為 starShip
和 rgbTuple
。
export type RgbType = [number, number, number] | string;
export function validateRGB(rgbValues: RgbType): string {
if (typeof rgbValues === 'string') {
return rgbValues;
}
const minRGB = 0;
const maxRGB = 255;
const [r, g, b] = rgbValues.map(value => Math.max(minRGB, Math.min(value, maxRGB)));
return `rgb(${r}, ${g}, ${b})`;
}
validateRGB
是一個接受字串或元組並傳回 RGB 值的函數。
import { Component, input } from '@angular/core';
import { RgbType, validateRGB } from './rgb';
@Component({
selector: 'app-star-war',
standalone: true,
template: '...',
})
export class StarWarComponent {
// signal input with transform
rgbs = input.required({
alias: 'rgbTuple',
transform: (v: RgbType) => validateRGB(v)
});
}
變換函數將輸入 (input) 轉換為 RGB 代碼 (RGB code)。
import { Component } from '@angular/core';
import { StarWarComponent } from './star-war.component';
@Component({
selector: 'app-root',
standalone: true,
imports: [StarWarComponent],
template: `
<app-star-war [jedi]="1" rgbTuple="yellow" />
<app-star-war [jedi]="10" [sith]="44" starShip="Jedi starfighter" [rgbTuple]="lightBlue" />
`,
})
export class App {
lightBlue = [137, 207, 240] as [number, number, number];
}
lightBlue
值轉換為 rgb(137, 207, 240)
; 黃色並按原樣傳回。
我們可以根據 signal input
建立 computed signal
。
import { NgStyle } from '@angular/common';
import { Component, computed, input } from '@angular/core';
import { RgbType, validateRGB } from './rgb';
@Component({
selector: 'app-star-war',
standalone: true,
imports: [NgStyle],
template: `<div [ngStyle]="backgrounStyle()"></div>`,
})
export class StarWarComponent {
// signal input with transform
rgbs = input.required({
alias: 'rgbTuple',
transform: (v: RgbType) => validateRGB(v)
});
// computed signal based on signal input
backgrounStyle = computed(() => ({
backgroundColor: this.rgbs()
}));
}
backgroundStyle
傳回背景顏色的 CSS 樣式。 CSS 樣式的背景顏色值等於rgbs
signal input。然後,backgroundStyle
signal的值被分配到NgStyle
。
import { Component, inject, Injector, input, signal } from '@angular/core';
import { getPerson, Person } from './star-war.api';
import { toObservable, toSignal } from '@angular/core/rxjs-interop';
import { switchMap } from 'rxjs';
@Component({
selector: 'app-star-war',
standalone: true,
imports: [StarWarPersonComponent],
template: `
<p>Sith Id: {{ sith() }}</p>
<app-star-war-person [person]="sithLord()" kind="Sith Lord" />`,
})
export class StarWarComponent {
// optional signal input with a value
sith = input(4);
injector = inject(Injector);
sithLord = toSignal(toObservable(this.sith).pipe(switchMap((v) => getPerson(v, this.injector))));
}
類似地,StarWarComponent
也可以使用 toObservable
將signal input
轉換為 Observable
。 在範例中,該組件將 sith
signal input轉換為 Observable
,並將 id
傳送到函數以檢索星際大戰人物。最後,toSignal
函數會取得 Observable
,建立一個signal
,並將其指派給 sithLord
。
@Component({
selector: 'app-star-war',
standalone: true,
imports: [StarWarPersonComponent],
template: `
<app-star-war-person [person]="sithLord()" kind="Sith Lord" />
`,
})
export class StarWarComponent {}
在範本中,sithLord
是 StarWarPersonComponent
的輸入 (input),用於顯示人物的詳細資料。
import {Component, input } from '@angular/core';
import { Person } from './star-war.api';
@Component({
selector: 'app-star-war-person',
standalone: true,
template: `
@let p = person();
@if(p) {
<p>Name: {{ p.name }}</p>
<p>Height: {{ p.height }}</p>
} @else {
<p>No info</p>
}
</div>`,
})
export class StarWarPersonComponent {
// required signal input
person = input<Person | undefined>(undefined);
}
StarWarPersonComponent
有一個必需的person
signal input來顯示那個人的詳細資料。
類似地,effect
可以追蹤signal input
執行程式碼。 StarWarComponent
在effect
中使用jedi
signal input,呼叫 Star War API
來檢索人物,並設定fighter
signal。訂閱 Observable
後,OnCleanUp
清理函數會在銷毀effect
前取消subscription
。
import { Component, effect, inject, Injector, input, signal } from '@angular/core';
import { getPerson, Person } from './star-war.api';
import { StarWarPersonComponent } from './star-war-person.component';
@Component({
selector: 'app-star-war',
standalone: true,
imports: [StarWarPersonComponent],
template: `
<p>Jedi Id: {{ jedi() }}</p>
<app-star-war-person [person]="fighter()" kind="Jedi Fighter" />`,
})
export class StarWarComponent {
// required signal input
jedi = input.required<number>();
injector = inject(Injector);
fighter = signal<Person | undefined>(undefined);
constructor() {
effect((OnCleanup) => {
const sub = getPerson(this.jedi(), this.injector)
.subscribe((result) => this.fighter.set(result));
OnCleanup(() => sub.unsubscribe());
});
}
}
在範本中,fighter
是StarWarPersonComponent
的輸入,用於顯示人物的詳細資料。
signal inputs
是保存signal
的輸入。signal inputs
可以是必需的 (required) 或可選的 (optional)。signal inputs
一個別名 (alias) 或一個變換函數 (transformation function來轉換輸入值。computed signal
可以從signal input
得出新值。toObservable
可以從signal input
建立一個新的Observable
。effect
可以追蹤signal input
執行程式碼。鐵人賽的第12天就這樣結束了。